<template>
  <div class="popover" ref="popover">
    <div class="contentWrapper" :class="{[`position-${position}`]:true}" ref="contentWrapper" v-if="visible">
      <slot name="content"></slot>
    </div>
    <div class="triggerWrapper" ref="triggerWrapper">
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: 'zPopover',
  props: {
    position: {
      type: String,
      default: 'top',
      validator (value) {
        return ['top', 'bottom', 'left', 'right'].indexOf(value) >= 0
      }
    },
    trigger: {
      type: String,
      default: 'click',
      validator (value) {
        return ['click', 'hover'].indexOf(value) >= 0
      }
    }
  },
  data () {
    return {
      visible: false
    }
  },
  mounted () {
    this.init()
  },
  beforeDestroy () {
  },
  computed: {
  },
  methods: {
    init () {
      if (this.trigger === 'click') {
        this.$refs.triggerWrapper.addEventListener('click', this.open)
      } else {
        this.$refs.triggerWrapper.addEventListener('mouseenter', this.open)
        this.$refs.triggerWrapper.addEventListener('mouseleave', this.close)
      }
    },
    open () {
      this.visible = true
      if (this.visible) {
        this.$nextTick(() => {
          this.positionContent()
          document.body.addEventListener('click', this.onClickDocument)
        })
      }
    },
    onClickDocument (e) {
      this.close(e)
    },
    close (e) {
      if (this.visible) {
        if (this.$refs.contentWrapper && this.$refs.contentWrapper.contains(e.target)) {
          return
        }
        if (this.trigger === 'click') {
          if (this.$refs.triggerWrapper && this.$refs.triggerWrapper.contains(e.target)) {
            return
          }
        }
        document.removeEventListener('click', this.onClickDocument)
        this.visible = false
      }
    },
    positionContent () {
      const { triggerWrapper, contentWrapper } = this.$refs
      const { width, height, top, left } = triggerWrapper.getBoundingClientRect()
      document.body.appendChild(contentWrapper)
      const positions = {
        top: {
          left: window.scrollX + left + 'px', top: window.scrollY + top + 'px'
        },
        bottom: {
          left: window.scrollX + left + 'px', top: window.scrollY + top + height + 'px'
        },
        left: {
          left: window.scrollX + left + 'px', top: window.scrollY + top + 'px'
        },
        right: {
          left: window.scrollX + left + width + 'px', top: window.scrollY + top + 'px'
        }
      }
      contentWrapper.style.left = positions[this.position].left
      contentWrapper.style.top = positions[this.position].top
      contentWrapper.style.height = height - 2 + 'px'
      contentWrapper.style.lineHeight = height - 2 + 'px'
    }
  }
}
</script>

<style scoped lang="scss">
.popover {
  display: inline-block;
}
.contentWrapper {
  position: absolute;
  border: 1px solid #666;
  border-radius: 2px;
  background-color: #ffffff;
  padding-left: 10px;
  padding-right: 10px;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
  &::before, &::after {
    content: '';
    display: block;
    border: 10px solid transparent;
    width: 0;
    height: 0;
    position: absolute;
  }
  &.position-top {
    transform: translateY(-100%);
    margin-top: -10px;
    &::before, &::after {
      left: 10px;
  }
  &::before {
    border-top-color: black;
    border-bottom: none;
    top: 100%;
  }
  &::after {
    border-top-color: white;
    border-bottom: none;
    top: calc(100% - 1px);
    }
  }
  &.position-bottom {
    margin-top: 10px;
    &::before, &::after {
      left: 10px;
    }
    &::before {
      border-top: none;
      border-bottom-color: black;
      bottom: 100%;
    }
    &::after {
      border-top: none;
      border-bottom-color: white;
      bottom: calc(100% - 1px);
    }
  }
  &.position-left {
    transform: translateX(-100%);
    margin-left: -10px;
    &::before, &::after {
      transform: translateY(-50%);
      top: 50%;
    }
    &::before {
      border-left-color: black;
      border-right: none;
      left: 100%;
    }
    &::after {
      border-left-color: white;
      border-right: none;
      left: calc(100% - 1px);
    }
  }
  &.position-right {
    margin-left: 10px;
    &::before, &::after {
      transform: translateY(-50%);
      top: 50%;
    }
    &::before {
      border-right-color: black;
      border-left: none;
      right: 100%;
    }
    &::after {
      border-right-color: white;
      border-left: none;
      right: calc(100% - 1px);
    }
  }
}
</style>
